<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>为已有类添加方法</title>
</head>

<body>
  <script>
    class Complex {
      // 在这种类字段声明标准化之后，我们可以像下面这样，声明私有字段来保存复数的
      // 实数和虚数部分：
      // #r=0；#i=0

      // 下面构造函数定义了他需要在每个实例上
      // 创建的实例属性r和i。这两个字段保存
      // 复数的实数和虚数部分，即对象的状态
      constructor(real, imaginary) {
        this.r = real;
        this.i = imaginary
      }
      // 这里是两个实例方法，用于做复数的加法和乘法。如果c和d是这个类两个实例，则可以写c.plus(d)或d.times(c)
      plus(that) {
        return new Complex(this.r + that.r, this.i + that.i)
      }
      times(that) {
        return new Complex(this.r * that.r - this.i * that.i, this.r * that.i + this.i * that.r)
      }

      // 这里是两个复数计算方法的静态版本。这样可以写Complex.sum（c,d）和Complex.product(c,d)
      static sum(c, d) { return c.plus(d) }
      static product(c, d) { return c.times(d) }

      // 这些也是实例方法，但是使用获取函数定义的，因此可以像使用字段一样使用它们。如果我们使用的是私有字段this.#r和this.#i，那这里的获取方法就有用了
      get real() { return this.r }
      get imaginary() { return this.i }
      get magnitude() { return Math.hypot(this.r, this.i) }

      // 每个类都应该有一个toString（）方法
      toString() { return `{${this.r},${this.i}}` }

      // 这个方法可以用来测试类的两个实例是否表示相同的值
      equals(that) {
        return that instanceof Complex && this.r == that.r && this.i == that.i
      }
      // 如果类体支持静态字段，那我们就可以像下面这样定义一个常量Complex.ZERO:static ZERO=new Complex(0,0)
    }
    Complex.prototype.conj = function () { return new Complex(this.r, -this.i) }
    console.log(new Complex(1, 2));

  </script>
</body>

</html>